package ru.bytedog.oiot.counter.bot.service;

import org.apache.commons.lang3.StringUtils;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Captor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import org.springframework.test.context.support.AnnotationConfigContextLoader;
import org.springframework.web.client.RestTemplate;
import ru.bytedog.oiot.counter.bot.bean.oiot.IOiotResponse;
import ru.bytedog.oiot.counter.bot.bean.oiot.OiotCounterData;
import ru.bytedog.oiot.counter.bot.bean.oiot.OiotResultData;
import ru.bytedog.oiot.counter.bot.bean.oiot.OiotSuccessResponse;
import ru.bytedog.oiot.counter.bot.config.RestIntegrationConfiguration;
import ru.bytedog.oiot.counter.bot.entity.BotUser;
import ru.bytedog.oiot.counter.bot.service.adapter.LocalDateTimeAdapter;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.Map;

import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.ArgumentMatchers.*;
import static org.mockito.Mockito.doReturn;

@ExtendWith(SpringExtension.class)
@ContextConfiguration(loader = AnnotationConfigContextLoader.class, classes = {LocalDateTimeAdapter.class, RestIntegrationConfiguration.class, OiotIntegrationService.class})
class OiotIntegrationServiceTest {

    @MockBean
    RestTemplate template;
    @Autowired
    OiotIntegrationService service;
    @Captor
    ArgumentCaptor<Map<String, Object>> urlParamsCaptor;


    @Test
    void loadUserLastCounterValueEmptyResponse() {
        BotUser user = getTestUser();
        doReturn(new ResponseEntity<>(StringUtils.EMPTY, HttpStatus.OK)).when(template).getForEntity(anyString(), eq(String.class), urlParamsCaptor.capture());

        IOiotResponse errorEmpty = service.loadUserLastCounterValue(user);
        assertTrue(errorEmpty.getBotMessage().contains(OiotIntegrationService.ERROR_MESSAGE));
        Map<String, Object> params = urlParamsCaptor.getValue();
        assertEquals(user.getOiotUserId(), params.get(OiotIntegrationService.PARAM_ID));
        assertEquals(user.getOiotUserToken(), params.get(OiotIntegrationService.PARAM_TOKEN));
        assertEquals(LocalDate.now().format(OiotIntegrationService.DATE_PARAM_FORMATTER), params.get(OiotIntegrationService.PARAM_DATE));
    }

    @Test
    void loadUserLastCounterValueErrorResponse() {
        doReturn(new ResponseEntity<>("{\"errors\":[\"Bad authtorise.\"]}", HttpStatus.OK)).when(template).getForEntity(anyString(), eq(String.class), anyMap());
        IOiotResponse errorResponse = service.loadUserLastCounterValue(getTestUser());
        assertTrue(errorResponse.getBotMessage().contains("Ошибка авторизации"));
    }

    @Test
    void loadUserLastCounterValueSuccessResponse() {
        doReturn(new ResponseEntity<>("{\"success\":true,\"result\":{\"20B36B3602AB48ABDC3A3EFA290F0C4A\":{\"TITLE\":\"\\u041a\\u0443\\u0445\\u043d\\u044f\",\"COUNTER_NAME_1\":\"\\u0413\\u043e\\u0440\\u044f\\u0447\\u0430\\u044f \\u0432\\u043e\\u0434\\u0430\",\"COUNTER_NAME_2\":\"\\u0425\\u043e\\u043b\\u043e\\u0434\\u043d\\u0430\\u044f \\u0432\\u043e\\u0434\\u0430\",\"COUNTER_CODE_1\":\"\",\"COUNTER_CODE_2\":\"\",\"MEASURE_1_NAME\":\"\\u043c.\\u043a\\u0443\\u0431.\",\"MEASURE_2_NAME\":\"\\u043c.\\u043a\\u0443\\u0431.\",\"data\":[{\"counter_1\":\"3.384\",\"counter_2\":\"35.964\",\"date\":\"2024-02-04 00:51:04\"}]}}}", HttpStatus.OK)).when(template).getForEntity(anyString(), eq(String.class), anyMap());
        OiotSuccessResponse response = (OiotSuccessResponse) service.loadUserLastCounterValue(getTestUser());
        OiotResultData data = response.getResult().get("20B36B3602AB48ABDC3A3EFA290F0C4A");
        assertEquals("Кухня", data.getTitle());
        assertEquals("Горячая вода", data.getCounterName1());
        assertEquals("Холодная вода", data.getCounterName2());
        assertEquals(data.getMeasure1(), data.getMeasure2());
        assertEquals(data.getMeasure1(), "м.куб.");
        OiotCounterData counter = data.getData().get(0);
        assertEquals("3.384", counter.getCounter1());
        assertEquals("35.964", counter.getCounter2());
        assertEquals(LocalDateTime.of(2024, 2, 4, 0, 51, 4), counter.getDate());
    }

    private BotUser getTestUser() {
        BotUser user = new BotUser();
        user.setOiotUserId("1");
        user.setOiotUserToken("2");
        return user;
    }
}